/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package pr3.gui;

import java.awt.Color;
import java.util.Collection;

import org.math.plot.Plot2DPanel;

import pr3.AlgoritmoGenetico;
import pr3.AlgoritmoGeneticoArbol;
import pr3.cromosoma.CromosomaArbol;
import pr3.cruce.EstrategiaCruce;
import pr3.mutacion.EstrategiaMutacion;
import pr3.seleccion.EstrategiaSeleccion;

/**
 * 
 * @author Gonzalo Ortiz Jaureguizar (gortiz at software.imdea.org)
 */
public class AGRunner {
	int generaciones;
	int tamPoblacion;
	double probCruce;
	double probMutacion;
	double precision;
	double escalado;
	int profMax;
	int profMin;
	EstrategiaSeleccion<CromosomaArbol> seleccion;
	EstrategiaCruce<CromosomaArbol> cruce;
	EstrategiaMutacion<CromosomaArbol> mutacion;
	AlgoritmoGenetico<CromosomaArbol> ag;
	int elitismo;

	public void plot(Plot2DPanel plot) {
		int guardados = elitismo * tamPoblacion / 100;
		ag = new AlgoritmoGeneticoArbol(tamPoblacion, guardados, true, profMax, profMin);

		ag.setCruce(cruce);
		ag.setProbCruce(probCruce / 100);
		ag.setProbMutacion(probMutacion / 100);
		ag.setSeleccion(seleccion);
		ag.setMutacion(mutacion);
		ag.setEscalado(true);

		double[] mejorHistorico = new double[generaciones + 1];
		double[] mejorActual = new double[generaciones + 1];
		double[] media = new double[generaciones + 1];

		plot.removeAllPlots();

		mejorHistorico[0] = ag.getMejor().getAdaptacion();
		mejorActual[0] = ag.getMejorActual().getAdaptacion();
		media[0] = calcularMedia(ag.getPoblacion());

		int topeEscalado = (int) (generaciones * escalado);

		for (int i = 1; i <= generaciones; i++) {
			ag.setEscalado(topeEscalado <= generaciones);
			ag.nuevaIteracion();
			mejorHistorico[i] = ag.getMejor().getAdaptacion();
			mejorActual[i] = ag.getMejorActual().getAdaptacion();
			media[i] = calcularMedia(ag.getPoblacion());
		}

		plot.addLinePlot("Maximo historico", Color.BLUE, mejorHistorico);
		plot.addLinePlot("Maximo actual", Color.RED, mejorActual);
		plot.addLinePlot("Media", Color.GREEN, media);
	}

	private double calcularMedia(Collection<CromosomaArbol> cromosomas) {
		double media = 0;
		for (CromosomaArbol c : cromosomas) {
			media += c.getAdaptacion();
		}
		return media / cromosomas.size();
	}

	public boolean chequearCondicionesIniciales() {
		if (generaciones <= 0) {
			throw new IllegalStateException(
					"El numero de generaciones no es positivo");
		}
		if (tamPoblacion <= 0) {
			throw new IllegalStateException(
					"El tamaño de la poblacion no es positivo");
		}
		if (probCruce < 0) {
			throw new IllegalStateException(
					"La probabilidad de cruce no puede ser negativa");
		}
		if (probMutacion < 0) {
			throw new IllegalStateException(
					"La probabilidad de mutacion no puede ser negativa");
		}
		if (precision <= 0) {
			throw new IllegalStateException("La precision debe positiva");
		}
		if (mutacion == null) {
			throw new IllegalStateException(
					"Se debe iniciar la estrategia de mutacion");
		}
		if (cruce == null) {
			throw new IllegalStateException(
					"Se debe iniciar la estrategia de cruce");
		}
		if (seleccion == null) {
			throw new IllegalStateException(
					"Se debe iniciar la estrategia de seleccion");
		}
		return true;
	}

	public int getTamPoblacion() {
		return tamPoblacion;
	}

	public void setTamPoblacion(int tamPoblacion) {
		this.tamPoblacion = tamPoblacion;
	}

	public int getGeneraciones() {
		return generaciones;
	}

	public void setGeneraciones(int generaciones) {
		this.generaciones = generaciones;
	}

	public double getPrecision() {
		return precision;
	}

	public void setPrecision(double precision) {
		this.precision = precision;
	}

	public double getProbCruce() {
		return probCruce;
	}

	public void setProbCruce(int probCruce) {
		this.probCruce = probCruce;
	}

	public double getProbMutacion() {
		return probMutacion;
	}

	public void setProbMutacion(int probMutacion) {
		this.probMutacion = probMutacion;
	}

	public EstrategiaCruce<CromosomaArbol> getCruce() {
		return cruce;
	}

	public void setCruce(EstrategiaCruce<CromosomaArbol> cruce) {
		this.cruce = cruce;
	}

	public EstrategiaMutacion<CromosomaArbol> getMutacion() {
		return mutacion;
	}

	public void setMutacion(EstrategiaMutacion<CromosomaArbol> mutacion) {
		this.mutacion = mutacion;
	}

	public EstrategiaSeleccion<CromosomaArbol> getSeleccion() {
		return seleccion;
	}

	public void setSeleccion(EstrategiaSeleccion<CromosomaArbol> seleccion) {
		this.seleccion = seleccion;
	}

	public int getElitismo() {
		return elitismo;
	}

	public void setElitismo(int elitismo) {
		this.elitismo = elitismo;
	}

	public double getEscalado() {
		return escalado;
	}

	public void setEscalado(double escalado) {
		this.escalado = escalado;
	}

	public double getMejorPuntuacion() {
		return ag.getMejor().evalua();
	}

	public CromosomaArbol getMejor() {
		return ag.getMejor();
	}

	public int getProfMax() {
		return profMax;
	}

	public void setProfMax(int profMax) {
		this.profMax = profMax;
	}

	public int getProfMin() {
		return profMin;
	}

	public void setProfMin(int profMin) {
		this.profMin = profMin;
	}

	public void setProbCruce(double probCruce) {
		this.probCruce = probCruce;
	}

	public void setProbMutacion(double probMutacion) {
		this.probMutacion = probMutacion;
	}

}
